using System;
using System.Collections.Generic;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;

namespace converter.template.item
{
    /// <summary>
    /// A text run -- a part of paragraph.
    /// </summary>
    internal class TextRun : TemplateItem
    {
        // The value evaluation mode.
        public enum EvaluationMode
        {
            Auto,
            Constant,
            Expression,
        }

        public TextRun(string value, EvaluationMode mode = EvaluationMode.Auto)
        {
            this.value = value;
            SetEvaluationMode(mode, value);
        }

        /// <summary>
        /// Builds a text run element. This is a leaf node.
        /// </summary>
        /// <param name="parent">A parent element -- Paragraph.</param>
        public override void Build(OpenXmlCompositeElement parent)
        {
            Run run = new Run();
            RunProperties properties = new RunProperties();

            // Is bold?
            if (GetStyle().Font.IsBold)
                properties.Append(new Bold());

            // Is italic?
            if (GetStyle().Font.IsItalic)
                properties.Append(new Italic());

            // Font family
            string fontFamily = GetStyle().Font.Family;
            RunFonts fonts = new RunFonts() { Ascii = fontFamily, HighAnsi = fontFamily, ComplexScript = fontFamily };
            properties.Append(fonts);

            // Font size
            FontSize fontSize = new FontSize() { Val = GetStyle().Font.HalfPointMeasurement };
            FontSizeComplexScript fontSizeComplexScript = new FontSizeComplexScript() { Val = GetStyle().Font.HalfPointMeasurement };
            properties.Append(fontSize);
            properties.Append(fontSizeComplexScript);

            Text text = new Text();
            text.Text = value;

            run.Append(properties);
            run.AppendChild(text);

            parent.AppendChild(run);
        }

        public bool IsExpression()
        {
            return mode == EvaluationMode.Expression;
        }

        public string GetValue()
        {
            return value;
        }

        public void SetValue(string newValue)
        {
            value = newValue;
        }

        // If the mode is Auto, then infer it from the value. That is, if
        // the value starts with =, treat it as an expression, otherwise constant.
        // After this call the mode should be anything but Auto.
        private void SetEvaluationMode(TextRun.EvaluationMode mode, string value)
        {
            if (mode == EvaluationMode.Auto)
                this.mode = value.StartsWith("=") ? EvaluationMode.Expression : EvaluationMode.Constant;
            else
                this.mode = mode;
        }

        private EvaluationMode mode;
        private string value;
    }
}
